// FilterableImage.java
//
// Informatics 102 Spring 2012
// Assignment #2: Metadata and Reflection
//
// This class implements a simple wrapper over Java's image-handling classes.
// It presents a view of an image as a two-dimensional array of ints, where
// each cell indicates the color of the pixel at a particular (x, y)
// coordinate.  The coordinate system used is the same one typically used
// in computer graphics, where (0, 0) is the upper-left corner of the image,
// x-coordinates increase to the right, and y-coordinates increase downward.
//
// The color of each pixel is indicated by an int value in what is called
// RGB form.  The lower eight bits of each int is an amount of blue (from
// 0 through 255), the next eight bits are the amount of green, and the
// next eight bits are the amount of red, with the upper eight bits
// representing an alpha value (i.e., a measure of transparency).

package inf102.assignment2.filters;

import java.awt.image.BufferedImage;


public class FilterableImage
{
	private int width;
	private int height;
	private int[][] pixels;
	
	
	// Constructs a FilterableImage from a Java BufferedImage.
	public FilterableImage(BufferedImage bufferedImage)
	{
		width = bufferedImage.getWidth();
		height = bufferedImage.getHeight();
		
		pixels = new int[width][height];
		
		for (int x = 0; x < width; x++)
		{
			for (int y = 0; y < height; y++)
			{
				try
				{
					pixels[x][y] = bufferedImage.getRGB(x, y);
				}
				catch (Exception e)
				{
					return;
				}
			}
		}
	}
	
	
	// getWidth() returns the width, in pixels, of this image.
	public int getWidth()
	{
		return width;
	}
	

	// getHeight() returns the height, in pixels, of this image.
	public int getHeight()
	{
		return height;
	}
	
	
	// getPixels() returns a two-dimensional array of the pixels that make
	// up this image.  Note that arrays are objects, so it is possible to
	// directly modify this array to modify the pixels of the image.
	public int[][] getPixels()
	{
		return pixels;
	}
	

	// resize() changes the width and height of an image.  It is also
	// necessary to supply a new two-dimensional array of pixels; this
	// class doesn't support resizing of images natively.
	//
	// If the size of the two-dimensional array doesn't match the given
	// width and height, this method throws an IllegalArgumentException.
	public void resize(int newWidth, int newHeight, int[][] newPixels)
	{
		requireArraySizeMatchesWidthAndHeight(newWidth, newHeight, newPixels);

		width = newWidth;
		height = newHeight;
		pixels = newPixels;
	}
	
	
	// convertToBufferedImage() converts this image to a Java
	// BufferedImage object, suitable to be displayed in a user interface.
	public BufferedImage convertToBufferedImage()
	{
		BufferedImage bufferedImage =
			new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		
		for (int x = 0; x < width; x++)
		{
			for (int y = 0; y < height; y++)
			{
				bufferedImage.setRGB(x, y, pixels[x][y]);
			}
		}
		
		return bufferedImage;
	}


	// requireArraySizeMatchesWidthAndHeight() checks if the given two-
	// dimensional array has the given width and height, throwing an
	// IllegalArgumentException if not.
	private void requireArraySizeMatchesWidthAndHeight(
		int newWidth, int newHeight, int[][] newPixels)
	{
		final String ERROR_MESSAGE = "Array size does not match width and height";
		
		if (newPixels.length != newWidth)
		{
			throw new IllegalArgumentException(ERROR_MESSAGE);
		}

		for (int x = 0; x < newPixels.length; x++)
		{
			if (newPixels[x].length != newHeight)
			{
				throw new IllegalArgumentException(ERROR_MESSAGE);
			}
		}
	}
}
